﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Xml.Linq;
using System.Linq;
using Docentric.Examples.Data.PlainDataSets;
using Docentric.Word;


namespace Docentric.Examples.Browser
{
	public class PlainDataSetExample : ExampleBase
	{
		// Constructor
		public PlainDataSetExample()
		{
			Name = "PlainDataSet";
			Title = "Plain Data Set";
			Description = "Plain Data Tables cannot be used as data sources directly. This example shows how easily can DataTables be used to populate a report. There is more than one technique to accomplish this but here the 'Purchase Orders' DataTable is first converted into an XML document which is then fed into the report. (Running this exemple requires MS Access 2010)";
		}


		// GenerateReport
		public override string GenerateReport()
		{
			// Load all purchase orders from the Northwind database.
			DataTable purchaseOrdersDataTable = DataAccess.LoadPurchaseOrders();

			// Plain DataTables can't be directly used as data sources. Convert the 'Purchase Orders' data table to an XML fragment which in turn will be used as the default data source value.
			DataTableToXmlConverter converter = new DataTableToXmlConverter(purchaseOrdersDataTable);
			XElement purchaseOrdersXElement = converter.GetXml();

			// Create a temporary file for the generated report document.
			string reportDocumentFileName = System.IO.Path.GetTempPath() + "GeneratedReport_" + Guid.NewGuid().ToString() + ".docx";
			using (Stream reportDocumentStream = File.Create(reportDocumentFileName))
			{
				// Open the report template file.
				using (Stream reportTemplateStream = GetReportTemplate())
				{
					// Generate the report document using 'DocumentGenerator'.
					DocumentGenerator dg = new DocumentGenerator(purchaseOrdersXElement);
					dg.ElementInitialize += new ElementInitializeHandler(dg_ElementInitialize);		// Hook to the 'ElementInitialize' in order to be able to provide values for unbound elements.
					DocumentGenerationResult result = dg.GenerateDocument(reportTemplateStream, reportDocumentStream);
					if (result.HasErrors)
					{
						foreach (Word.Error error in result.Errors) Console.Out.WriteLine(error.Message);
					}
				}
			}

			return reportDocumentFileName;
		}


		private void dg_ElementInitialize(object sender, ElementInitializeEventArgs e)
		{
			if (e.Element.Name == "FLD_TotalPrice")
			{
				// The current data context is an object of type 'NorthwindDataSet.Purchase_Order_DetailsRow'.
				XElement currentPurchaseOrderDetailXElement = (XElement)((IEnumerable<XObject>)e.Element.DataContext.Value).FirstOrDefault();

				// Calculate the total price.
				e.Element.AsField().Value = decimal.Parse(currentPurchaseOrderDetailXElement.Attribute("Quantity").Value, System.Globalization.CultureInfo.InvariantCulture) *
											decimal.Parse(currentPurchaseOrderDetailXElement.Attribute("Unit_Cost").Value, System.Globalization.CultureInfo.InvariantCulture);
			}
		}


		/// <summary>
		/// Writes the schema of the 'Purchase Orders' DataTable (including related rows from other DataTables in the Northwind DataSet) to a file in the form of the XSD.
		/// This method should be called each time the schema is changed. The file is written in the project directory.
		/// The XSD is not mendatory for the document generation process. We only need it to import it into our document template as a data source schema in order to gain help from the Add-In.
		/// </summary>
		public void WriteSchemaToFile()
		{
			// Load all purchase orders from the Northwind database.
			DataTable purchaseOrdersDataTable = DataAccess.LoadPurchaseOrders();

			// Write XSD representing the 'root' data table to disk.
			DataTableToXmlConverter tmpConverter = new DataTableToXmlConverter(purchaseOrdersDataTable);
			var xmlSchema = tmpConverter.GetXmlSchema();
			string xsdFileName = System.IO.Path.Combine(ApplicationPath, "ExampleResources\\" + Name + "\\PurchaseOrdersSchema.xsd");
			if (File.Exists(xsdFileName)) File.Delete(xsdFileName);	// Delete if it already exists.
			using (FileStream fs = File.Create(xsdFileName))
			{
				xmlSchema.Write(fs);
			}
		}
	}
}
